import hashlib
import os
import time
import tkinter.messagebox as msgbox
from itertools import chain
from tkinter import filedialog


def add_folder():
    star_folder = r"C:\MyPrograms\MyPython\Projects\repeating-check-master"
    folder_path = filedialog.askdirectory(initialdir=star_folder)
    return folder_path


def show_choice_dialog():
    result = msgbox.askquestion("选择", "你还要添加文件夹吗？")
    if result == "yes":
        return True
    else:
        return False


def delete_choose():
    result = msgbox.askquestion("选择", "是否删除多余重复文件？")
    if result == "yes":
        return True
    else:
        return False


def get_files(directory, file_list):
    for root, dirs, files in os.walk(directory):
        for file in files:
            file_list.append(os.path.join(root, file))
    return file_list


def get_file_md5(fname):
    m = hashlib.md5()  # 创建md5对象
    with open(fname, 'rb') as fobj:
        while True:
            data = fobj.read(4096)
            if not data:
                break
            m.update(data)  # 更新md5对象

    return m.hexdigest()  # 返回md5对象


def find_the_same_files(the_files_md5_dict):
    new_dict = {}
    for key, value in the_files_md5_dict.items():
        new_dict.setdefault(value, set()).add(key)
    the_same_file_list = []
    for key, value in new_dict.items():
        if (len(value) > 1):
            the_same_file_list.append(value)
    return the_same_file_list


def delete_file(the_same_file_list):
    for s in the_same_file_list:
        file_path_list = list(s)
        for f in file_path_list[1:]:
            if os.path.exists(f):
                os.remove(f)
                if os.path.exists(f):
                    print(f"{f}，删除失败")
                else:
                    print(f"{f}，删除成功")
            else:
                print(f"{f}，不存在，删除失败")


if __name__ == "__main__":

    # 程序计时
    start_time = time.time()

    # 1，while循环利用文件夹选择器获取用输入的文件夹
    folder_set = set()
    folder_set.add(add_folder())
    while show_choice_dialog():
        folder_set.add(add_folder())

    # 2，获取所有文件夹下的所有文件
    file_list = []
    file_set = set()
    for folder in folder_set:
        file_list = get_files(folder, file_list)

    # 3，获取所有文件的大小
    for file in file_list:
        file = file.replace("/", os.sep).replace("\\", os.sep)
        file_set.add(file)

    file_size_dict = {}

    for file in file_set:
        stats = os.stat(file)
        file_size = stats.st_size
        file_size_dict[file] = file_size

    # 4，找出相同大小的文件
    rev_multidict = {}
    for key, value in file_size_dict.items():
        rev_multidict.setdefault(value, set()).add(key)

    the_same_size_files = set(chain.from_iterable(values for key, values in rev_multidict.items() if len(values) > 1))

    # 5，对相同大小的文件求MD5
    the_files_md5_dict = {}
    for file in the_same_size_files:
        file_md5 = get_file_md5(file)
        the_files_md5_dict[file] = file_md5

    # 6，找出相同MD5的文件
    the_same_file_list = find_the_same_files(the_files_md5_dict)

    # 7，弹窗让用户决定是否由程序删除多余重复文件
    if len(the_same_file_list) > 0:
        print("-------重复文件如下-------")

        for i in the_same_file_list:
            print(i)

        time.sleep(2)

        flag = delete_choose()
        if flag:
            delete_file(the_same_file_list)
    else:
        print("没发现重复文件")

    end_time = time.time()
    print("程序结束，耗时：{:.2f}秒".format(end_time - start_time))
